import java.awt.BorderLayout;
import javax.swing.*;
import org.ini4j.Ini;


/**
 * Main Class of the project
 * @author Luc Peres
 * @version 2.0
 */
public class Simulation extends JPanel{
	private Cell cell;
	private Periplasm periplasm;
	
	private JTextArea textArea;
	private Ini params;

	/**
	 * Class constructor, create the needed Objects and run the simulation loop
	 */
	public Simulation() {
		params = Param.getParam().getParams();
		this.setupGUI();
		cell = new Cell();
		periplasm = new Periplasm();
		int cycle = 0;		
		this.print(cycle, textArea);
		cycle ++;
		while (cycle <= Integer.parseInt(params.get("Simulation", "Cycle Number")))
		{
			this.compute();
			this.print(cycle, textArea);
			cycle++;
		}
	}
	
	/**
	 * Format the program's GUI
	 */
	private void setupGUI() {
		this.textArea = new JTextArea();
		this.textArea.setEditable(false);
		this.setLayout(new BorderLayout());
		JScrollPane scrollPane = new JScrollPane(this.textArea);
		this.add(scrollPane);
		this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
	}
	
	/**
	 * Creates the Window and the Simulation instance
	 * @param args
	 */
	public static void main(String[] args) {
		Simulation simulation = new Simulation();
		JFrame frame = new JFrame("Bacterial Simulation");
		frame.setSize(1200, 500);
		frame.setLocationRelativeTo(null);
		frame.add(simulation);
		frame.setContentPane(simulation);
		frame.setVisible(true);
		System.out.println("End of Simulation");
		
	}
	
	/**
	 * Executes all the rules defining interaction between each molecule or protein in the simulation
	 */
	private void compute() {
		double ratio;
		
		ratio = 1 / (cell.getCbl() * Double.parseDouble(params.get("Cell/ratio", "Cbl --<> gshA")));
		cell.setgshA(cell.getgshA() * ratio);
		
		ratio = 1 / (cell.getCbl() * Double.parseDouble(params.get("Cell/ratio", "Cbl --<> gshB")));
		cell.setgshB(cell.getgshB() * ratio);
		
		ratio = 1 * (cell.getGSSG() * Double.parseDouble(params.get("Cell/ratio", "GSSG --> GSH")))
		/ (cell.getGor() * Double.parseDouble(params.get("Cell/ratio", "Gor --<> GSH")))
		* (cell.getgshA() * Double.parseDouble(params.get("Cell/ratio", "gshA --> GSH")))
		* (cell.getgshB() * Double.parseDouble(params.get("Cell/ratio", "gshB --> GSH")));
		cell.setGSH(cell.getGSH() * ratio);
		
		ratio = 1 * (cell.getGSH() * Double.parseDouble(params.get("Cell/ratio", "GSH --> GSSG")));
		cell.setGSSG(cell.getGSSG() * ratio);
		
		ratio = 1 * (cell.getGSH() * Double.parseDouble(params.get("CellPeriplasm/ratio", "GSH(Cell) --> GSH(Periplasm)")));
		periplasm.setGSH(periplasm.getGSH() * ratio);
		
		ratio = 1 * (periplasm.getGSH() * Double.parseDouble(params.get("Periplasm/ratio", "GSH --> GSSG")))
		* (periplasm.getO2() * Double.parseDouble(params.get("Periplasm/ratio", "O2 --> GSSG")));
		periplasm.setGSSG(periplasm.getGSSG() * ratio);
		
		ratio = 1 / (periplasm.getO2() * Double.parseDouble(params.get("CellPeriplasm/ratio", "O2(Periplasm) --<> ArcB(Cell)")));
		cell.setArcB(cell.getArcB() * ratio);
		
		ratio = 1 * (cell.getArcB() * Double.parseDouble(params.get("Cell/ratio", "ArcB --> ArcA-P")));
		cell.setArcAP(cell.getArcAP() * ratio);
		
		ratio = 1 / (periplasm.getGSH() * Double.parseDouble(params.get("CellPeriplasm/ratio", "GSH(Periplasm) --<> put(Cell)")));
		cell.setput(cell.getput() * ratio);
		
		ratio = 1 / (cell.getput() * Double.parseDouble(params.get("Cell/ratio", "put --<> fimB")));
		cell.setfimB(cell.getfimB() * ratio);
		
		ratio = 1 * (cell.getfimB() * Double.parseDouble(params.get("Cell/ratio", "fimB --> FimB")));
		cell.setFimB(cell.getFimB() * ratio);
		
		ratio = 1 * (cell.getFimB() * Double.parseDouble(params.get("Cell/ratio", "FimB --> fimS")))
		/ (cell.getGSSG() * Double.parseDouble(params.get("Cell/ratio", "GSSG --<> fimS")))
		/ (cell.getArcAP() * Double.parseDouble(params.get("Cell/ratio", "ArcA-P --<> fimS")));
		cell.setfimS(cell.getfimS() * ratio);
	}
	
	/**
	 * Print the results cycle by cycle in the window's textArea
	 * @param cycle
	 * @param textArea
	 */
	private void print(int cycle, JTextArea textArea) {
		textArea.setText(textArea.getText() + "Cycle: " + cycle);
		cell.print(textArea);
		periplasm.print(textArea);
		textArea.setText(textArea.getText() + '\n');
	}
}
